/***************************************************************
This class maintains a a sequence of pointers to GeneralNCUs.
Each instance that is pointed by the pointer is instantiated as one 
type of NCUs of the four types.  The major fuctions of this class are to
assign the model configuration according to a specification specified by
users and calculate the output according to the input.
!!!Caution.
Before using the class NCUCModel, users shall configure the configuration
of the model so that the parameters of the corresponding model can be assigned
properly.
A design pattern, factory, is used in this class to generate NCU objects.

!!!!!!!!Caution!!!!!!!!!!!
Boost library is used in this class.  share_ptr is used for managing the 
memory.
Author:Chun-Ming Wang

Date of Modification: 01/12/2007 (dd/mm/yyyy)
***************************************************************/
#pragma once
#ifndef _NCUCModel
#define _NCUCModel
#include <vector>
#include <string>
#include <boost/shared_ptr.hpp>
#include "Misc.h"
#include "GeneralNCU.h"
#include "TypeANCU.h"
#include "TypeBNCU.h"
#include "TypeCNCU.h"
#include "TypeDNCU.h"
#include "EDCFactor.h"
using namespace std;
using namespace boost;
class NCUCModel
{
public:
	typedef vector<double> doubleContainer;
	typedef doubleContainer::iterator doubleIter;
	typedef doubleContainer::const_iterator doubleConstIter;
	typedef boost::shared_ptr<GeneralNCU> NCUPTR;
	// constructors
	NCUCModel();
	NCUCModel(const string &conf);
	NCUCModel(const string &conf, const doubleContainer & paras);
	NCUCModel(const NCUCModel &rhs);
	// destructor
	~NCUCModel();
	// copy assignment
	NCUCModel& operator=(const NCUCModel &rhs);
	NCUCModel* clone() const;
	// access function
	// assign the area(in square km) to the EDCFactor
	void area(const double& a);
	// assign the simulation time interval (in minutes)
	void interval(const unsigned int& i);
	// assign the configuration of the NCUC model
	void config(const string &conf);
	// get the configuration of the NCUC model 
	const string config() const;
	// assign the parameters of the NCUC model
	bool parameters(const doubleContainer &paras);
	// get the parameters of the NCUC model
	const doubleContainer parameters() const;
	// simulating an event. The output is the equivalent depth
	vector<double> simulation(const doubleContainer &input);
	// simulating an event. The output is the flow rate (cubic meter/s)
	vector<double> runoff(const doubleContainer &input);
	// get the number of parameters contained in the model
	const unsigned int number() const;
	// get the genome informaton of the NCUC model
	vector<const GenomeType*> genome() const;
	// assign the boundaries and the length of the genome of sill variables
	void sillBound(const double lower, const double upper,
		const unsigned int length);
	// assign the boundaries and the length of the genome of output coefficient variables
	void ventBound(const unsigned int length);
protected:
	// a factory generates a instance of a NCU with a specification specified by users
	NCUPTR factory(const NCULabel &tag);
	// converting a string into a NCULabel
	NCULabel label(const string &tag);
	// validating the character of the identity of a NCU
	bool check_id(const char &id);
	// reset the status of NCUC model
	void reset();
	// simulating one input
	const outputPair step(const double &input) const;
	// duplicate a NCUCModel in the right hand side
	void duplicate(const NCUCModel &rhs); 
private:
	typedef vector<NCUPTR> NCUContainer;
	typedef NCUContainer::iterator NCUContainerIter;
	typedef NCUContainer::const_iterator NCUConstContainerIter;
	NCUContainer m_seq;
	EDCFactor m_factor;
	//bool _simulated;
};
#endif